package com.jincp.common.function;

import android.text.TextUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by jinchunping on 2019/2/21.
 */

public class FunctionManager {

    private static FunctionManager instance;

    private Map<String, FunctionHasParamHasResult> functionHasParamHasResult;
    private Map<String, FunctionNoParamNoResult> functionNoParamNoResult;
    private Map<String, FunctionHasParamNoResult> functionHasParamNoResult;
    private Map<String, FunctionNoParamHasResult> functionNoParamHasResult;

    public static FunctionManager getInstance() {
        if (instance == null) {
            synchronized (FunctionManager.class) {
                if (instance == null) {
                    instance = new FunctionManager();
                }
            }
        }
        return instance;
    }

    private FunctionManager() {
        functionHasParamHasResult = new HashMap<>();
        functionNoParamNoResult = new HashMap<>();
        functionHasParamNoResult = new HashMap<>();
        functionNoParamHasResult = new HashMap<>();
    }

    public FunctionManager addFunction(Function function) {
        if (function instanceof FunctionHasParamHasResult) {
            functionHasParamHasResult.put(function.mFunctionName, (FunctionHasParamHasResult) function);
        } else if (function instanceof FunctionNoParamNoResult) {
            functionNoParamNoResult.put(function.mFunctionName, (FunctionNoParamNoResult) function);
        } else if (function instanceof FunctionHasParamNoResult) {
            functionHasParamNoResult.put(function.mFunctionName, (FunctionHasParamNoResult) function);
        } else if (function instanceof FunctionNoParamHasResult) {
            functionNoParamHasResult.put(function.mFunctionName, (FunctionNoParamHasResult) function);
        }
        return this;
    }

    public <Param, Result> Result invokeFunction(String functionName, Param param, Class<Result> c) {
        if (TextUtils.isEmpty(functionName)) {
            return null;
        }
        if (functionHasParamHasResult != null) {
            FunctionHasParamHasResult f = functionHasParamHasResult.get(functionName);
            if (f != null) {
                if (c != null) {
                    return c.cast(f.invoke(param));
                } else {
                    return (Result) f.invoke(param);
                }
            } else {
                //抛异常 :接口未注册
                new FunctionNotFoundException("has no this invoke " +
                        functionName).printStackTrace();
            }
        }
        return null;
    }

    public void invokeFunction(String functionName) {
        if (TextUtils.isEmpty(functionName)) {
            return;
        }
        if (functionNoParamNoResult != null) {
            FunctionNoParamNoResult f = functionNoParamNoResult.get(functionName);
            if (f != null) {
                f.invoke();
            } else {
                //抛异常 :接口未注册
                new FunctionNotFoundException("has no this invoke " +
                        functionName).printStackTrace();
            }
        }
    }

    public <Param> void invokeFunction(String functionName, Param param) {
        if (TextUtils.isEmpty(functionName)) {
            return;
        }
        if (functionHasParamNoResult != null) {
            FunctionHasParamNoResult f = functionHasParamNoResult.get(functionName);
            if (f != null) {
                f.invoke(param);
            } else {
                //抛异常 :接口未注册
                new FunctionNotFoundException("has no this invoke " +
                        functionName).printStackTrace();
            }
        }
    }

    public <Result> Result invokeFunction(String functionName, Class<Result> c) {
        if (TextUtils.isEmpty(functionName)) {
            return null;
        }
        if (functionNoParamHasResult != null) {
            FunctionNoParamHasResult f = functionNoParamHasResult.get(functionName);
            if (f != null) {
                if (c != null) {
                    return c.cast(f.invoke());
                } else {
                    return (Result) f.invoke();
                }
            } else {
                //抛异常 :接口未注册
                new FunctionNotFoundException("has no this invoke " +
                        functionName).printStackTrace();
            }
        }
        return null;
    }
}
